Regexp dxl help

Recently I started practicing with regexp to search for certain words/text that I would need to look for in a module.

Im trying to do a script to search for the word Section and any corresponding numbers after it (i.e. Section 2.3.4.1.5....etc) and once it reaches the end of the number and it comes across a letter then it stops and displays just the number.

Example.

ID Object Heading & Object Text Section ID's (This column is inserted when I run the script)
1234 This is some text with the word and number Section 3.2.1.4. Once is reaches the end it stops and displays the section and # in the next column. The script with search all the text to check is there are multiple Sections. If it finds Section 3.3.5.1 it will also display in the next column.

Section 3.2.1.4

Section 3.3.5.1

5678 Another line of text containing Section 8.5.2.4. This will display in the next column Section 8.5.2.4

 

The DXL manual is confusing when it's explaining the different setups you can use , I also think I understand that it is possible to add multiple expressions together based off of the manual's example. (I could be wrong)

Regexp URL = regexp2 "(HTTP|http|ftp|FTP|file|FILE)://([^ \\),;>\"]*)"
string txt3 = "The ABC URL is http://www.abc.com; it may be..."
if (URL txt3) {
print txt3[match 0] "\n" // whole match
print txt3[match 1] "\n" // first section in ()
print txt3[match 2] "\n" // second section in ()
}

Right now my code here:

//====================================
//SearchReplaceUppperCaseSectionNo.dxl
//====================================
pragma runLim, 0
pragma stack, 1000000

Module m = current
Object o

load view "Standard view"
filtering off

//========================
//Check for Exclusive Edit
//========================
if ((isRead current Module)||(isShare current Module))
 {
  ack"Module must be opened in [Exclusive Edit]"
            halt 
 }
else
 {

 }

//=================================
//START=====Find Delete Create TEMP
//=================================
string err
AttrDef adTEMP = find (current Module, "TEMP")

if (exists attribute "TEMP") 
 {
  err = delete(adTEMP)
  if (!null err) 
     {
       ack err
     }
  }
create object type "text" history false changeBars false date false attribute "TEMP"
width(column 0, 100)

//===================
//START===Insert TEMP
//===================

insert(column 2)        
attribute(column 2, "TEMP")
width(column 2, 200)
justify(column 2, left)

title (column 2, "Section Spelling Errors")

//============
//MAIN PROGRAM
//============
Skip mySkip = createString

int numAbbr = 0

bool findOneNum  (Object o) 
 {
  Regexp searcherOneNum1 = regexp2 "^[sS]ection ([0-9]+$)"
  Regexp searcherOneNum2 = regexp2 "[sS]ection ([0-9] $)"
  Regexp searcherOneNum3 = regexp2 " [sS]ection ([0-9]$)"
  Regexp searcherOneNum4 = regexp2 "[sS]ection ([0-9], +$)"
  Regexp searcherOneNum5 = regexp2 "[sS]ection ([0-9].+$)"      
    
  int shEnd, sEndTotal, sEnd, lRest 
    int i
    int from = 0

  string cont
  
  bool foundOne = false
    bool done = false
    bool atEnd = false
    bool result = false

           Buffer txt = create
                                              
   txt = o."Object Text"
 
  string ss = null
                                                                         
   while ( (search(searcherOneNum1, txt, from))||
    (search(searcherOneNum2, txt, from))||
    (search(searcherOneNum3, txt, from))||
    (search(searcherOneNum4, txt, from))||
    (search(searcherOneNum5, txt, from))
   )
   {
       int starter = start 0
          int offset = end 0 
                                                                    
          string match = txt[from + starter  :from +offset]   
           
          ss= match
         
          o."TEMP" = o."TEMP"ss"\n"
       
         from += offset + 1
           
       put(mySkip,match,numAbbr)
     numAbbr++
     
    }
  delete txt  
   return result
 }
for o in document m do 
 {               
       findOneNum (o)
                                                         
 }
delete (mySkip)

refresh current Module

Filter f = contains(attribute "TEMP", ".*", false, true)
set f

filtering on

refresh current Module

Almost does what I am trying to get it to do.

The results I get finds about 90% of (Section ##) but it misses some of them that are in the middle of text and when It does find it in the middle of text it sometimes will continue to show the text following the numbers.

Example:

Object Text Section ID
This is some text in the module. It contains Section 1.2.3.4. The following column show then only show Section 1.2.3.4 but it shows all text after the first Section 1.2.3.4. Section 1.2.3.4. The following column show then only show Section 1.2.3.4 but it shows all text after the first Section 1.2.3.4.

Testing

Section 1

Section 2 (space after)

 Section 3 (space before)

Section 4, (comma)

Section 5. (period)

Section 6 (

Section 1

Section 2

 Section 3

Section 4,

Section 5.

Section 6 (

Here is some more text with Section 1.2.3.4. It's not finding the Section and number in this text for some reason. But it will still find the list of Sections afterwards.

Section 1

Section 1.2

Section 1.2.1

Section 1.2.1.2

Section 1.2.1.2.1

Section 1.2.1.2.1.2

Section 1.2.1.2.1.2.1

Section 1.2.1.2.1.2.1.2

Section 1.2.1.2.1.2.1.2.1

Section 1.2.1.2.1.2.1.2.1.2

Section 1.2.3.4 (this should also be included but it isn't being found)

Section 1

Section 1.2

Section 1.2.1

Section 1.2.1.2

Section 1.2.1.2.1

Section 1.2.1.2.1.2

Section 1.2.1.2.1.2.1

Section 1.2.1.2.1.2.1.2

Section 1.2.1.2.1.2.1.2.1

Section 1.2.1.2.1.2.1.2.1.2

What I've read in the manual says that.

[^abc]

any character except a, b, or c

Does something like [^a-zA-Z] also work the same way?

Let me know if I need to give more info if this doesn't make any sense. Any and all help would be appreciative.

(I'd like to figure this out before all my hair turns grey, my wife already jokes about it enough as it is haha.)


MrNiceGuy - Wed May 31 11:44:12 EDT 2017

Re: Regexp dxl help
Mathias Mamsch - Thu Jun 01 03:33:39 EDT 2017

First I find it kind of intriguing to do something like this: 

while (  search(...) || search(...) || search(...) ) {
   int x = start 0, y = end 0; 
   ...
}

start 0 and end 0 always apply to the most recent application of a regexp and while the above should work (because we assume that the other search(...) expressions are not invoked once any search returns true, you are relying on an undocumented syntax feature that might change or not in the future. If DXL would execute all search expressions and then calculate the result, start 0 and end 0 would always refer to the last one even if that returned false. 

Secondly I think your problems were caused by your regular expressions. 

  Regexp searcherOneNum1 = regexp2 "^[sS]ection ([0-9]+$)"
  Regexp searcherOneNum2 = regexp2 "[sS]ection ([0-9] $)"
  Regexp searcherOneNum3 = regexp2 " [sS]ection ([0-9]$)"
  Regexp searcherOneNum4 = regexp2 "[sS]ection ([0-9], +$)"
  Regexp searcherOneNum5 = regexp2 "[sS]ection ([0-9].+$)"  

- Note all of them have a $ at the end meaning they will only match at the end of the line. So if the number is in the middle of the text no expression will match (except the last one which always matches up the end of the line)

- Note also that searcherOneNum5 will match everything after "Section 1" because the "." matches any character so your expression will also match to  "Section 1abc.Whatever!"

I would suggest if you want to match section numbers you can make one regular expression out of it: 

"[sS]ection +([0-9]+\\.)*[0-9]+( +\\([^)]+\\))?"

    A            B         C        D

or something similar ...

A => matches the word section and one or more spaces
B => matches the first (optional) part of the heading e.g. 3.4.
C => matches the last part of the heading e.g. 5
D => matches some optional text in parenthesis

This way you do not need to iterate twice (once for the numbers and once for each digit inside the number) and you do not need to use multiple regexps. 

Maybe this helps, regards, Mathias

 

Re: Regexp dxl help
MrNiceGuy - Thu Jun 01 12:47:16 EDT 2017

Mathias Mamsch - Thu Jun 01 03:33:39 EDT 2017

First I find it kind of intriguing to do something like this: 

while (  search(...) || search(...) || search(...) ) {
   int x = start 0, y = end 0; 
   ...
}

start 0 and end 0 always apply to the most recent application of a regexp and while the above should work (because we assume that the other search(...) expressions are not invoked once any search returns true, you are relying on an undocumented syntax feature that might change or not in the future. If DXL would execute all search expressions and then calculate the result, start 0 and end 0 would always refer to the last one even if that returned false. 

Secondly I think your problems were caused by your regular expressions. 

  Regexp searcherOneNum1 = regexp2 "^[sS]ection ([0-9]+$)"
  Regexp searcherOneNum2 = regexp2 "[sS]ection ([0-9] $)"
  Regexp searcherOneNum3 = regexp2 " [sS]ection ([0-9]$)"
  Regexp searcherOneNum4 = regexp2 "[sS]ection ([0-9], +$)"
  Regexp searcherOneNum5 = regexp2 "[sS]ection ([0-9].+$)"  

- Note all of them have a $ at the end meaning they will only match at the end of the line. So if the number is in the middle of the text no expression will match (except the last one which always matches up the end of the line)

- Note also that searcherOneNum5 will match everything after "Section 1" because the "." matches any character so your expression will also match to  "Section 1abc.Whatever!"

I would suggest if you want to match section numbers you can make one regular expression out of it: 

"[sS]ection +([0-9]+\\.)*[0-9]+( +\\([^)]+\\))?"

    A            B         C        D

or something similar ...

A => matches the word section and one or more spaces
B => matches the first (optional) part of the heading e.g. 3.4.
C => matches the last part of the heading e.g. 5
D => matches some optional text in parenthesis

This way you do not need to iterate twice (once for the numbers and once for each digit inside the number) and you do not need to use multiple regexps. 

Maybe this helps, regards, Mathias

 

Im going to have to read the manual a few dozen more times because I still don't understand how that all works together yet. But thank you very much for the reply and help Mathias your expression works perfectly.

 

Re: Regexp dxl help
MrNiceGuy - Mon Jun 05 12:19:40 EDT 2017

Mathias Mamsch - Thu Jun 01 03:33:39 EDT 2017

First I find it kind of intriguing to do something like this: 

while (  search(...) || search(...) || search(...) ) {
   int x = start 0, y = end 0; 
   ...
}

start 0 and end 0 always apply to the most recent application of a regexp and while the above should work (because we assume that the other search(...) expressions are not invoked once any search returns true, you are relying on an undocumented syntax feature that might change or not in the future. If DXL would execute all search expressions and then calculate the result, start 0 and end 0 would always refer to the last one even if that returned false. 

Secondly I think your problems were caused by your regular expressions. 

  Regexp searcherOneNum1 = regexp2 "^[sS]ection ([0-9]+$)"
  Regexp searcherOneNum2 = regexp2 "[sS]ection ([0-9] $)"
  Regexp searcherOneNum3 = regexp2 " [sS]ection ([0-9]$)"
  Regexp searcherOneNum4 = regexp2 "[sS]ection ([0-9], +$)"
  Regexp searcherOneNum5 = regexp2 "[sS]ection ([0-9].+$)"  

- Note all of them have a $ at the end meaning they will only match at the end of the line. So if the number is in the middle of the text no expression will match (except the last one which always matches up the end of the line)

- Note also that searcherOneNum5 will match everything after "Section 1" because the "." matches any character so your expression will also match to  "Section 1abc.Whatever!"

I would suggest if you want to match section numbers you can make one regular expression out of it: 

"[sS]ection +([0-9]+\\.)*[0-9]+( +\\([^)]+\\))?"

    A            B         C        D

or something similar ...

A => matches the word section and one or more spaces
B => matches the first (optional) part of the heading e.g. 3.4.
C => matches the last part of the heading e.g. 5
D => matches some optional text in parenthesis

This way you do not need to iterate twice (once for the numbers and once for each digit inside the number) and you do not need to use multiple regexps. 

Maybe this helps, regards, Mathias

 

So I've looked everywhere and I cant seem to figure out what the ? does for regexp.

unless im reading over it I don't see it in the manual. Could you explain what that does exactly?

 

Re: Regexp dxl help
Mike.Scharnow - Mon Jun 05 17:05:49 EDT 2017

MrNiceGuy - Mon Jun 05 12:19:40 EDT 2017

So I've looked everywhere and I cant seem to figure out what the ? does for regexp.

unless im reading over it I don't see it in the manual. Could you explain what that does exactly?

 

funny, it seems that IBM really forgot to mention that. ? in DXL has the same meaning as in all other languages that support regular expressions, see e.g. https://en.wikipedia.org/wiki/Regular_expression, chapter 3 "Basic Concepts".

In Mathias' Post this would mean that pattern D may exist or not, it is optional.